﻿using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.Events;

public class DraggableUI : BaseUI, IBeginDragHandler, IDragHandler, IEndDragHandler
{
    private Vector2 pointerOffset;

    public UnityEvent onBeginDrag = new UnityEvent();
    public UnityEvent<PointerEventData> onBeginDragWithData = new UnityEvent<PointerEventData>();

    public UnityEvent onDrag = new UnityEvent();
    public UnityEvent<PointerEventData> onDragWithData = new UnityEvent<PointerEventData>();

    public UnityEvent onEndDrag = new UnityEvent();
    public UnityEvent<PointerEventData> onEndDragWithData = new UnityEvent<PointerEventData>();

    // 注册方法 AddXXX
    public void AddBeginDrag(UnityAction action) => onBeginDrag.AddListener(action);
    public void AddBeginDrag(UnityAction<PointerEventData> action) => onBeginDragWithData.AddListener(action);

    public void AddDrag(UnityAction action) => onDrag.AddListener(action);
    public void AddDrag(UnityAction<PointerEventData> action) => onDragWithData.AddListener(action);

    public void AddEndDrag(UnityAction action) => onEndDrag.AddListener(action);
    public void AddEndDrag(UnityAction<PointerEventData> action) => onEndDragWithData.AddListener(action);

    public void Awake()
    {
        rectTransform = GetComponent<RectTransform>();
    }

    // 实现接口方法并触发事件
    public void OnBeginDrag(PointerEventData eventData)
    {
        RectTransformUtility.ScreenPointToLocalPointInRectangle(
            rectTransform,
            eventData.position,
            eventData.pressEventCamera,
            out pointerOffset
        );

        onBeginDrag.Invoke();
        onBeginDragWithData.Invoke(eventData);
    }

    public void OnDrag(PointerEventData eventData)
    {
        Vector2 localPoint;
        RectTransformUtility.ScreenPointToLocalPointInRectangle(
            rectTransform.parent as RectTransform,
            eventData.position,
            eventData.pressEventCamera,
            out localPoint
        );

        rectTransform.localPosition = localPoint - pointerOffset;
        ClampPosition();

        onDrag.Invoke();
        onDragWithData.Invoke(eventData);
    }

    public void OnEndDrag(PointerEventData eventData)
    {
        onEndDrag.Invoke();
        onEndDragWithData.Invoke(eventData);
    }

    private void ClampPosition()
    {
        RectTransform parentRect = rectTransform.parent as RectTransform;

        Vector3[] corners = new Vector3[4];
        rectTransform.GetWorldCorners(corners);

        Vector3[] parentCorners = new Vector3[4];
        parentRect.GetWorldCorners(parentCorners);

        for (int i = 0; i < 4; i++)
        {
            corners[i].x = Mathf.Clamp(corners[i].x, parentCorners[0].x, parentCorners[2].x);
            corners[i].y = Mathf.Clamp(corners[i].y, parentCorners[0].y, parentCorners[2].y);
        }

        rectTransform.position = (corners[0] + corners[2]) / 2;
    }
}